Real-Time Payments & FedNow: Engineering Guide
Real-time payment rails such as FedNow change the engineering contract for moving money: settlement is instant, continuously available, and irrevocable once accepted. For teams used to Automated Clearing House (ACH) batches or other returnable rails, retry logic and reconciliation delays become correctness risks.
Your payment service retries a pacs.008 after a 19-second timeout. The first attempt actually settled. Now you have two irrevocable credits sitting in a recipient's account, and while you can initiate a best-effort return flow (camt.056 followed by pacs.004), there is no guaranteed network-level reversal of the original payment, and a reconciliation team that won't see the duplicate until tomorrow morning. With FedNow, settlement is final once the Receiver financial institution (FI) accepts.
The cost of getting this wrong is not hypothetical. On August 11, 2020, Citigroup mistakenly wired $893 million to Revlon's lenders instead of a planned $7.8 million interest payment; a federal judge ruled the transfers "final and complete transactions, not subject to revocation." Citibank eventually recovered most of the money on appeal years later, your engineering team will not have that luxury on a pacs.008 that settled in 20 seconds.
Architecture that worked for batch rails will quietly produce duplicate charges and balance drift under instant, irrevocable settlement. Real-time settlement changes authorization, retry handling, ledger design, reconciliation, fraud controls, and uptime expectations.
How FedNow works: settlement, finality, and message flow
FedNow is a real-time gross settlement (RTGS) system. Every transaction settles individually at gross value, and settlement is immediate and irrevocable. Once a payment completes, it cannot be reversed. That single property drives every design decision below.
Settlement occurs when the service records master account debits and credits for the sending and receiving institutions, or their correspondents. A sending institution must hold sufficient funds in its Fed master account, or a designated correspondent's account, before FedNow will route the payment. This prefunding means settlement carries no credit risk to the network. The service runs 24×7×365 with no expectations of planned downtime, while ACH runs on business days and Fedwire has defined windows.
FedNow is built entirely on ISO 20022 XML. The standard customer credit transfer flow uses pacs.008 and is designed to complete the full round-trip in roughly 20 seconds under normal conditions:
- The sending FI screens the payment and submits a pacs.008 to FedNow via FedLine.
- FedNow validates the message format and verifies sufficient funds in the sender's master account.
- The Receiver FI responds with a pacs.002 status report. An ACTC response signals intent to accept.
- FedNow settles the master account debit and credit, then delivers pacs.002 confirmation to each FI.
- The Receiver FI is generally required to make funds available to the end customer immediately upon accepting the payment, with limited exceptions (for example, "accept without posting" where there is reasonable cause to delay posting for legal or fraud reasons).
FedNow is credit-push only. A Request for Payment (pain.013) signals the payee's request; the payer's FI still initiates the actual credit push. Returns use a separate pacs.004 message. The original payment remains final.
FedNow vs. RTP at a glance
Many US teams evaluating instant payments will run a dual-rail design. The two networks look similar at the application boundary but differ structurally:
| Dimension | FedNow | RTP (The Clearing House) |
| Operator | Federal Reserve | The Clearing House |
| Settlement model | RTGS against each participant's Fed master account | Prefunded joint account at FRBNY; TCH clears only |
| Launch | July 2023 | November 2017 |
| Per-transaction limit | $10M network ceiling (Nov 2025), $100K default | $10M (effective February 9, 2025) |
| Message standard | ISO 20022 | ISO 20022 |
| Availability | 24×7×365 | 24×7×365 |
| Finality | Immediate, irrevocable | Immediate, irrevocable |
| Participation roles | Receive-only, send-and-receive, LMT | Receive-only, send-and-receive |
Treat FedNow and RTP as separate rails in your application architecture unless your provider offers a bridge. Routing belongs in an orchestration layer above the Ledger, whether you build it in-house or use a workflow engine. Keep rail-specific logic out of the Ledger posting itself (see "Rail-agnostic postings" below).
The failure modes that break under irrevocable settlement
An ambiguous retry can create a duplicate payment. When your client sends a payment and receives no response, it may not know whether the request settled. Without protection, the retry can settle a second irrevocable payment.
On a returnable rail you had recourse. Here, the only remediation is a best-effort camt.056 return request followed by a pacs.004 payment return, and that depends on the receiving FI's cooperation.
Idempotency keys: the first line of defense
A common application-level protection is the idempotency key. The client generates a unique key on the first attempt and includes it in every retry. The server uses the key to detect duplicates: if it sees the same key twice, it returns the recorded result from the first attempt instead of executing again.
For payment writes, the idempotency layer should preserve both the original request parameters and the final outcome so retries cannot create a second business effect.
Avoiding race conditions
A cache still leaves a race condition if your implementation checks the store for the key, then processes, then stores the key. Two concurrent retries can both read "key not found" and both charge the customer.
A safer implementation inserts the idempotency key and executes the business operation in a single database transaction. For concurrent unseen keys, one request wins via a unique constraint or lock; others wait or receive a conflict response.
Watch the TTL boundary
If a key's TTL expires while the client is still inside its retry window, the retry finds no record and executes again. Key TTL should be set to outlast the client's maximum retry window, with margin.
Pair this with exponential backoff and jitter so a wave of retries does not produce a thundering herd.
What FedNow requires of you
FedNow's own procedures reflect how seriously the network treats duplicates. If a participant is uncertain whether a payment order was sent, it shall inquire first before submitting another order that might duplicate.
On the message layer, participants must:
- Confirm Business Application Header message IDs are unique.
- Match each payment to its pacs.002 settlement notification.
- Ignore duplicate settlement notifications.
Duplicate handling is your responsibility on both the send and receive paths.
Two architectural consequences
Two architectural choices follow directly from irrevocability:
- Consistent balance reads. Stale balance reads during a partition are unsafe for payment authorization; Ledger writes need a consistent balance source. A Ledger that stays available but returns stale balances can authorize payments you cannot cover.
- Append-only ledger as system of record. The system of record should be an append-only ledger. Corrections use compensating entries so the full lineage of every posting survives for the audit that irreversible payments will eventually trigger.
How reconciliation and ledger design change at 24/7/365
Real-time settlement breaks three assumptions that legacy ledgers quietly depend on: that reconciliation can run in batches, that a single wall-clock timestamp is enough to order events, and that a pooled bank balance is the same thing as a per-user balance. Real-time settlement makes each of those a hard correctness requirement rather than an optimization.
Month-end batch reconciliation is a poor fit for real-time settlement. Legacy reconciliation processes often assume batch cycles: transactions accumulate, reconciliations run in batches, and the books get brought current at period close. When money moves in seconds, around the clock, a discrepancy discovered at month-end is a discrepancy that may have been wrong for weeks, against settlements you cannot reverse.
Formance Reconciliation replaces that batch pattern. Bank transactions and Ledger records match as they arrive. The matching process cross-references amounts, dates, reference IDs, and counterparty data. Exceptions get flagged in near real time rather than surfacing days later. When Formance Reconciliation catches a duplicate, it flags the second posting as an exception, holds it from settlement, and surfaces it with the original transaction ID so the ops team can resolve it before it touches the ledger.
Double-entry enforced at the storage layer
A product ledger focuses on scarcity, concurrency, auditability, immutability, and performance. A general ledger organizes financial events to report a business's overall financial position. You plug the product ledger into your GL; the GL remains the reporting system. Every transaction touches two or more accounts in compensating directions, and balances derive from an immutable log rather than a mutable balance column.
Bi-temporality
A bi-temporal ledger stores two timestamps per posting: when the event actually happened, and when your system learned about it.
That separation matters because real-time settlement produces out-of-order arrivals: correspondent-processed returns, weekend liquidity transfers, late pacs.002 confirmations. A ledger that records only wall-clock time will produce wrong historical balances when those events land.
Bi-temporality keeps point-in-time balance queries correct regardless of arrival order. It is a correctness requirement for any system handling real-time settlement.
Virtual segregation of omnibus accounts
When you look at your bank portal, you see one pooled number. You see the pile without breaking it into "Ben has 50 USD" or "Alice has 100 USD." If the balance drops by 100 USD, you know money is missing but the portal cannot identify the affected customer. A SELECT SUM on the omnibus account returns 5,000 USD; your internal ledger shows 4,850 USD across all user accounts. The 150 USD gap is now traceable rather than a mystery.
Treat the omnibus account as a view over hierarchical account paths like user:ben:available, and book known costs (gas fees, FX spreads) to dedicated accounts like platform:operating:gasfees. That turns drift into data. The question shifts from "do our books match?" to "is the system healthy?", and you get the answer every minute.
How a posting stays rail-agnostic across FedNow and RTP
Your core Ledger should be rail-agnostic even when application routing treats FedNow and RTP as separate rails. The posting shape stays identical; only the source account changes. A FedNow settlement and an RTP settlement both credit the same user, and you preserve the rail of origin in the account path for reconciliation without leaking rail-specific logic into balance math:
send [USD/2 50000] (
source = @world:fednow:incoming
destination = @users:1234:available
)
send [USD/2 50000] (
source = @world:rtp:incoming
destination = @users:1234:available
)Both move $500 into @users:1234:available. The only difference is the source, which records where the money came from. This is Numscript, a purpose-built language for money that describes a transaction's intent in terms both engineers and finance teams can read. One script expresses the whole flow, and the Ledger commits all postings or none. The resulting record is audit-ready. When the camt.052 activity report arrives, you reconcile against the same posting shape regardless of rail.
For multi-step flows that span both rails, attempt FedNow, fall back to RTP on an admi.004 reject, wait for pacs.002 ACTC, then book the final credit, Formance Flows orchestrates the sequence in YAML with native retry and fallback, and writes the resulting postings to the Ledger atomically.
Fraud controls must run before settlement
Irrevocability moves fraud defense to the front of the payment. The pattern is already visible on Zelle, the closest US analog to FedNow on the consumer side. In December 2024, the Consumer Financial Protection Bureau filed a complaint against three of the country's largest banks and the operator of Zelle "for allowing fraud to fester" on that network, alleging that customers of JPMorgan Chase, Bank of America, and Wells Fargo lost more than $870 million since Zelle launched seven years ago. Because real-time payments are irrevocable, post-settlement controls can only attempt recovery.
Authorized payment scams are the dominant pattern to design against. Fraudsters deceive a victim into authorizing a payment, and because real-time payments are irrevocable, the victim cannot depend on reversal after the fact.
FedNow exposes pre-authorization tools, and the engineering decision is to call them before you initiate:
- Network Intelligence API: retrieve risk insights on a counterpart before sending pacs.008.
- Negative list: reject payments to or from a known RTN-and-account combination.
- Account activity thresholds: set value and velocity limits by customer segment.
- Step-up auth and cooling-off windows: application-layer controls for high-risk or first-time payees.
When a payment turns out fraudulent after settlement, the sender sends camt.056 with reason code FRAD and the receiver initiates pacs.004 returns with reason code FR01. These are best-effort recovery attempts, not reversals of final settlement.
Build versus buy under real-time constraints
Your team has to decide whether it can build a Ledger and keep maintaining it under the correctness constraints irrevocable settlement imposes. Idempotent postings that keep retries from polluting balances, immutable audit history, and continuous reconciliation against external statements are expensive to build correctly and worse to debug after the fact. A real-time rail gives you less time to unwind a correctness bug than a batch or returnable rail.
At Formance, we've built an open-source, programmable core Ledger that unifies fiat and digital assets with a regulatory-grade audit trail. The four properties real-time settlement demands, double-entry enforced in storage, append-only immutability, write idempotency, and per-entity account isolation, belong in the Ledger itself, not the application layer. You could build this on SQL, but you would be rebuilding the wheel: architecting double-entry constraints and custom locking to prevent race conditions before you even reach reconciliation logic.
Formance Connectivity normalizes data from banks and PSPs into one model and triggers payouts through connected providers, with pre-built connectors for US bank and BaaS partners relevant to FedNow and RTP, including JP Morgan and Cross River Bank via the Banking Bridge, plus Column, Increase, and Plaid, alongside PSPs like Stripe, Adyen, and Mangopay. Reconciliation compares your Ledger against that external data to catch drift as soon as it appears. Tito Sarrionandia, VP Engineering at Liberis, runs reconciliation across 14 countries on Formance with zero reconciliation errors across more than 1 million transactions. Newton, a Canadian crypto exchange built on Formance Ledger, processes $10M+ in daily volume at 50ms p95.
Formance Ledger is MIT-licensed and deployable on your own AWS, GCP, or Azure account, with a 50ms p95 and a 99.9% uptime SLA on the Enterprise tier.
With Formance Ledger, your team stops maintaining duplicate-detection and drift-detection plumbing and spends that time on the products real-time settlement actually makes possible, instant payouts, programmable wallets, and agent-initiated transactions.
Start by auditing your current retry logic: does it check for an existing settlement notification before re-submitting a pacs.008? Clone the Formance Ledger on GitHub, run it locally, and post your first dual-rail transaction with separate @world:fednow and @world:rtp source accounts to test rail-agnostic settlement against your reconciliation model.
Related Articles

Money Movement Architecture for Multi-Rail Fintechs
A practical guide to money movement architecture for fintechs running multiple payment rails. Learn how a ledger-first design absorbs new rails without compounding technical debt.

Why Modern Fintechs Layer a Ledger Under Their Core Banking System
Core banking and modern ledgers solve different problems. Learn the architectural split, why fintechs need both, and how to decide what to build or buy.

How to Develop a Crypto Payment Gateway for Multi-Rail Payments
Learn how to architect a multi-rail crypto payment gateway that handles USDC, USDT, fiat settlement, and new rails without breaking existing flows.